package com.fxu.gen;

import cn.hutool.core.util.StrUtil;
import com.fxu.framework.biz.base.Limits;
import com.fxu.framework.core.base.Constant;
import com.fxu.framework.core.enums.BaseEnum;
import com.fxu.framework.core.enums.ShowStatus;
import com.fxu.framework.core.enums.ShowStrStatus;
import com.fxu.framework.core.exception.MsgException;
import com.fxu.gen.enums.ClnType;
import com.fxu.gen.enums.FormType;
import com.fxu.gen.enums.QueryType;
import com.fxu.gen.enums.TplEnum;
import com.fxu.tpl.entity.Column;
import com.fxu.tpl.entity.Link;
import com.fxu.tpl.entity.Table;

import java.io.File;
import java.util.List;

/**
 * 基于vue+element
 * @author fangxu
 */
public final class VueHtml extends Base {
	private String showFlags = "";

	public VueHtml(Table table, File destFile) {
		super(table, TplEnum.VueHtml, destFile);
	}

	@Override
	public String doReplace() {
		fileTxt = fileTxt.replace("bean: 'user',", "bean: '"+this.thisModule+"."+StrUtil.lowerFirst(tableBean)+"',");
		if (table.getIsExport()) {
			fileTxt = fillByKey(fileTxt, ">新增</el-button>",
					"        <export-excel :bean=\"bean\" :params=\"getData\" :table-map=\"tableMap\" :file-name=\"'"+table.getCmmt()+"'\" />"); //  :on-filter="toFilter"
		}
		if (table.getIsImport()) {
			fileTxt = fillByKey(fileTxt, ">新增</el-button>",
					"        <import-excel :bean=\"bean\" :table-map=\"tableMap\" :file-name=\"'"+table.getCmmt()+"'\" />"); // :on-show="changeShow"
		}
		if (table.getIsExport() || table.getIsImport()) {
			fileTxt = fileTxt.replace("loadings: []", "loadings: [],\n      tableMap: {\n" + getTableMap("        ") + "\n      }");
			// fileTxt = fillByKey(fileTxt, "loadings: []", "      tableMap: {\n" + getTableMap("        ") + "\n      }");
		}

		fileTxt = fillByKey(fileTxt, "<!--自动生成搜索代码开始-->", getMainVueQuery(4));
		fileTxt = fillByKey(fileTxt, "<!--自动生成表格代码开始-->", getMainVueTable(3));
		fileTxt = fillByKey(fileTxt, "<!--自动生成编辑代码开始-->", getMainVueForm(4));
		fileTxt = fillByKey(fileTxt, "      editForm: {", getEditFormData().toString());
		fileTxt = fillByKey(fileTxt, "      formRules: {", getFormRules().toString());
		String temp = getTabPane(5);
		if (temp.length() > 0) {
			fileTxt = fileTxt.replace("<el-tabs size=\"mini\" />", "<el-tabs size=\"mini\">\n" + temp + "\n        </el-tabs>");
		}

		boolean hasCompts = false;
		String jsStartKey = "import api, { isAdmin } from '@/api/service'";
		if (fileTxt.contains("<my-select")) {
			fileTxt = fillByKey(fileTxt, jsStartKey, "import mySelect from '@/views/compts/input'");
			fileTxt = fillByKey(fileTxt, "components: {", "    mySelect" + (hasCompts ? "," : ""));
			hasCompts = true;
		}
		if (fileTxt.contains("<my-conf")) {
			fileTxt = fillByKey(fileTxt, jsStartKey, "import myConf from '@/views/compts/MyConf'");
			fileTxt = fillByKey(fileTxt, "components: {", "    myConf" + (hasCompts ? "," : ""));
			hasCompts = true;
		}
		if (fileTxt.contains("<upload-one")) {
			fileTxt = fillByKey(fileTxt, jsStartKey, "import uploadOne from '@/views/compts/upload'");
			fileTxt = fillByKey(fileTxt, "components: {", "    uploadOne" + (hasCompts ? "," : ""));
			hasCompts = true;
		}
		if (fileTxt.contains("<my-editor")) {
			fileTxt = fillByKey(fileTxt, jsStartKey, "import myEditor from '@/views/compts/MyEditor'");
			fileTxt = fillByKey(fileTxt, "components: {", "    myEditor" + (hasCompts ? "," : ""));
			hasCompts = true;
		}
		if (table.getIsExport()) {
			fileTxt = fillByKey(fileTxt, jsStartKey, "import ExportExcel from '@/views/compts/exportExcel'");
			fileTxt = fillByKey(fileTxt, "components: {", "    ExportExcel" + (hasCompts ? "," : ""));
			hasCompts = true;
		}
		if (table.getIsImport()) {
			fileTxt = fillByKey(fileTxt, jsStartKey, "import ImportExcel from '@/views/compts/importExcel'");
			fileTxt = fillByKey(fileTxt, "components: {", "    ImportExcel" + (hasCompts ? "," : ""));
		}
		// 填充时间间隔查询
		if (fileTxt.contains(":picker-options=\"pickerOptions\"")) {
			fileTxt = fillByKey(fileTxt, jsStartKey, "import { pickerOptions } from '@/utils/index'");
			fileTxt = fillByKey(fileTxt,"        formData: {}", "        pickerOptions: {\n        shortcuts: pickerOptions\n      },");
		}
		// 长字段显示
		if (BaseEnum.hasAny(columns, Column::isText)) {
			fileTxt = fillBeforeKey(fileTxt,"        params: {}", "        showText: true,");
		}

		if (showFlags.length() > 0) {
			fileTxt = fillBeforeKey(fileTxt,"        params: {}", "        showFlags: '" + showFlags + "',");
		}

		if (BaseEnum.hasAny(columns, cln -> cln.getLimits() != null && ShowStatus.is(cln.getLimits()))) {
			String editButton = "<el-table-column align=\"center\" fixed=\"right\" label=\"操作\" width=\"172px\">\n        <template slot-scope=\"scope\">";
			fileTxt = fillByKey(fileTxt, editButton, "          <el-button v-if=\"scope.row.status == 1\" :disabled=\"loadings[scope.$index]\" size=\"mini\" type=\"success\" @click=\"func.cmStatus(_self, scope, 2, '显示')\">显示</el-button>\n" +
					"          <el-button v-if=\"scope.row.status == 2\" :disabled=\"loadings[scope.$index]\" size=\"mini\" type=\"danger\" @click=\"func.cmStatus(_self, scope, 1, '隐藏')\">隐藏</el-button>\n" +
					"          <br>");
		}

		if (BaseEnum.hasAny(columns, cln -> cln.getLimits() != null && ShowStrStatus.is(cln.getLimits()))) {
			String editButton = "<el-table-column align=\"center\" fixed=\"right\" label=\"操作\" width=\"172px\">\n        <template slot-scope=\"scope\">";
			fileTxt = fillByKey(fileTxt, editButton, "          <el-button v-if=\"scope.row.status == 'HIDE'\" :disabled=\"loadings[scope.$index]\" size=\"mini\" type=\"success\" @click=\"func.cmStatus(_self, scope, 'SHOW', '显示')\">显示</el-button>\n" +
					"          <el-button v-if=\"scope.row.status == 'SHOW'\" :disabled=\"loadings[scope.$index]\" size=\"mini\" type=\"danger\" @click=\"func.cmStatus(_self, scope, 'HIDE', '隐藏')\">隐藏</el-button>\n" +
					"          <br>");
		}

		if (BaseEnum.hasAny(columns, cln -> cln.getLimits() != null && cln.getLimits().contains("DELETE:删除"))) {
			fileTxt = fileTxt.replace("api.cmStatus(this, scope, 0, command)", "api.cmStatus(this, scope, 'DELETE', command)");
		}

		/*if (AutoUtil.hasColumn(columns, Constant.CLN_ORDER_BY)) {
			fileTxt = fillByKey(fileTxt, "api.onEdit(this.$data, scope)", "      this.formData.orderBy = this.listData.total + 1");
		}*/
		return fileTxt;
	}

	// 获取查询表单
	private StringBuffer getMainVueQuery(int tab) {
		StrBuf buffer = new StrBuf(true);
		String clnName, clnCmmt;
		ClnType clnType; QueryType qryType; FormType formType;
		String priKeyName = getPriKeyClnName(columns);
		for (Column cln : columns) {
			if (cln.getQueryType() == null || cln.getQueryType() < 1 || priKeyName.equals(cln.getName())) {
				continue;
			}
			clnCmmt = getCmmt(cln, "");
			clnType = ClnType.find(cln.getType());
			qryType = QueryType.find(cln.getQueryType());
			clnName = AutoUtil.firstLowerBean(cln.getName());
			formType = FormType.find(cln.getFormType());
			StrBuf item = new StrBuf(true);

			if (clnType == ClnType.BOOLEAN) {
				item.append(tab + 1, "<el-select v-model=\"getData.params.{1}\" placeholder=\"请选择{2}\" clearable>", clnName, clnCmmt);
				item.append(tab + 2, "<el-option label=\"是\" value=\"true\" />");
				item.append(tab + 2, "<el-option label=\"否\" value=\"false\" />");
				item.append(tab + 1, "</el-select>");
			}
			else if (!StrUtil.isEmpty(cln.getLimits())) { // && !cln.getName().equals(Constant.CLN_STATUS)
				item.append(tab + 1, "<el-select v-model=\"getData.params.{1}\" placeholder=\"请选择{2}\" clearable>", clnName, clnCmmt);
				item.append(getLimitsHtml(cln.getLimits(), tab + 2, null));
				item.append(tab + 1, "</el-select>");
			}
			else if ((clnType == ClnType.DATE || clnType == ClnType.DATETIME) && (qryType == QueryType.RANGE_EQUALS || qryType == QueryType.RANGE_NOT_EQUALS)) {
				String format = formType == FormType.DATE ? "yyyy-MM-dd" : "yyyy-MM-dd HH:mm:ss";
				item.append(tab + 1, "<el-date-picker v-model=\"getData.{1}Array\"" +
						" :picker-options=\"pickerOptions\" type=\"daterange\" value-format=\"{2}\"" +
						" range-separator=\"至\" start-placeholder=\"{3}开始\" end-placeholder=\"{3}结束\"" +
						" align=\"right\" clearable />", clnName, format, clnCmmt);
			}
			else if (formType == FormType.SELECT || formType == FormType.MY_CONF) {
				item.append(tab + 1, getMyComp(formType, cln.getLinkTable(), table.getName(), "getData.params." + clnName, clnCmmt));
			} else {
				if (qryType == QueryType.LIKE || qryType == QueryType.RIGHT_LIKE) {
					clnName = qryType == QueryType.LIKE ? clnName + "$Lk" : clnName + "$LkRt";
				}
				item.append(tab + 1, "<el-input v-model=\"getData.params.{1}\" placeholder=\"请输入{2}\" clearable />", clnName, clnCmmt);
			}
			if (item.length() > 0) {
				buffer.append(tab, "<el-form-item>").append(item.toString()).append(tab, "</el-form-item>");
			}
		}
		return buffer.toBuffer();
	}

	private String getMyComp(FormType type, Table linkTable, String tableName, String vueName, String clnCmmt) {
		if (type == FormType.SELECT) {
			if (linkTable == null) {
				throw new MsgException("请选择" + tableName + "的" + vueName + "关联表!");
			}
			String linkBean = linkTable.getModule().getName() + "." + AutoUtil.firstLowerBean(linkTable.getName());
			return StrUtil.format("<my-select v-model=\"{}\" bean=\"{}\" placeholder=\"{}\" />", vueName, linkBean, clnCmmt);
		}
		return StrUtil.format("<my-conf :init=\"{}\" :params=\"{type: 'XXX'}\" bean=\"sysConf\"" +
				" placeholder=\"{}\" @change=\"val => {} = val\" />", vueName, clnCmmt, vueName);
	}

	// 整个表格显示
	private StringBuffer getMainVueTable(int tab) {
		StrBuf buffer = new StrBuf(true), lnkBuf = new StrBuf(true);
		links.stream().filter(link -> link != null && link.getLinkTable() != null).forEach(link -> {
			List<Column> lkColumns = link.getLinkTable().getColumnList();
			String data = getLinkPropName(link);
			if (isTrue(link.getIsList())) {
				showFlags += (showFlags.length() > 0 ? "," : "") + data + "List";
				data = StrUtil.format(":data=\"scope.row.{}List\"", data);
			} else {
				showFlags += (showFlags.length() > 0 ? "," : "") + data;
				data = StrUtil.format(":data=\"[scope.row.{}]\"", data);
			}
			lnkBuf.append(tab + 2, "<el-table "+data+" border fit highlight-current-row>");
			lnkBuf.append(getMainTable(lkColumns, "slot", tab + 3));
			lnkBuf.append(tab + 2, "</el-table>");
		});
		// 增加内容Text或者Blob展示或者String的长度>1024
		columns.stream().filter(this::isShowInDetail).forEach(cln -> {
			lnkBuf.append(tab + 2, "<el-table :data=\"[scope.row]\" border fit highlight-current-row>");
			lnkBuf.append(tab + 3, "<el-table-column prop=\"{1}\" label=\"{2}\" />", AutoUtil.firstLowerBean(cln.getName()), getCmmt(cln, null));
			lnkBuf.append(tab + 2, "</el-table>");
		});
		if (lnkBuf.length() > 0) {
			buffer.append(tab, "<el-table-column type=\"expand\" label=\"详情\" width=\"60px\">");
			buffer.append(tab + 1, "<template slot-scope=\"scope\">");
			buffer.append(lnkBuf);
			buffer.append(tab + 1, "</template>");
			buffer.append(tab, "</el-table-column>");
		}
		buffer.append(getMainTable(columns, "scope", tab));
		return buffer.toBuffer();
	}

	// 单个表格显示
	private StringBuffer getMainTable(List<Column> clnList, String slot, int tab) {
		StrBuf buffer = new StrBuf(true);
		String blank = StrBuf.tabStr(tab, true);
		for (Column cln : clnList) {
			// 内容Text或者Blob展示或者String的长度>1024
			if (!isTrue(cln.getListShow()) || isShowInDetail(cln)) {
				continue;
			}

			String clnComment = getCmmt(cln, null);
			String clnName = AutoUtil.firstLowerBean(cln.getName());
			String slotClnName = slot + ".row." + clnName;
			String overflow = isTrue(cln.getOverflow()) ? " :show-overflow-tooltip=\"true\"" : "";
			String clnWidth = cln.getListWidth() != null && cln.getListWidth() > 0 ? " width=\""+cln.getListWidth()+"\"" : "";

			if (cln.getLinkTable() != null) {
				String temp = !clnName.endsWith("Id") ? clnName : clnName.substring(0, clnName.length() - 2);
				showFlags += (showFlags.length() > 0 ? "," : "") + temp;
				clnName = temp + ".name";
				clnComment = getCmmt(cln, "");
			}
			String line = StrUtil.format("<el-table-column{} align=\"center\" prop=\"{}\" label=\"{}\"{}", overflow, clnName, clnComment, clnWidth);

			StrBuf scope = new StrBuf(true);
			if (!StrUtil.isEmpty(cln.getLimits())) {
				scope.append(getLimitsHtml(cln.getLimits(), tab + 2, slotClnName));
			}
			else if (cln.getType().intValue() == ClnType.BOOLEAN.code()) {
				scope.append(tab + 2, "<el-tag v-if=\"{1}\" size=\"mini\">是</el-tag>", slotClnName);
				scope.append(tab + 2, "<el-tag v-else size=\"mini\">否</el-tag>");
			}
			else if (cln.getType().intValue() == ClnType.DATE.code() || cln.getType().intValue() == ClnType.DATETIME.code()) {
				scope.append(tab + 2, "{{ {1} | parseDate() }}", slotClnName);
			}
			else if (cln.getFormType().intValue() == FormType.IMAGE.code()) { // 图片
				// scope.append(tab + 2, "<img v-if=\"{1}\" :src=\"{2}\" class=\"avatar\" style=\"width: 80px; height: 80px\">", slotClnName, slotClnName);
				scope.append(tab + 2, "<el-image v-if=\"{1}\" :src=\"{2}\" :preview-src-list=\"[{3}]\" class=\"avatar\" style=\"width: 80px; height: 80px\" />", slotClnName, slotClnName, slotClnName);
			}
			if (scope.length() > 0) {
				buffer.append(blank).append(line).append(">\n");
				buffer.append(tab + 1, "<template slot-scope=\"{1}\">", slot);
				buffer.append(scope);
				buffer.append(tab + 1, "</template>");
				buffer.append(tab, "</el-table-column>");
			} else {
				buffer.append(blank).append(line).append(" />\n");
			}
		}
		return buffer.toBuffer();
	}

	// 添加和编辑表单
	private String getMainVueForm(int tab) {
		StrBuf strBuf = new StrBuf(true);
		int rowCol = table.getRowCol() == null || table.getRowCol() < 0 ? 0 : table.getRowCol();
		for (Column column : columns) {
			if (isTrue(column.getFormShow())) {
				if (rowCol > 0) {
					strBuf.append(tab + 1, "<el-col>");
					strBuf.append(getFormItem(column, "formData", tab, ""));
					strBuf.append(tab + 1, "</el-col>");
				} else {
					strBuf.append(getFormItem(column, "formData", tab, ""));
				}
			}
		}
		if (strBuf.length() > 0) {
			if (rowCol > 0 && rowCol < 4) {
				strBuf.replace("<el-col>", "<el-col :xs=\"24\" :sm=\"12\">");
			} else if (rowCol > 0) {
				strBuf.replace("<el-col>", "<el-col :xs=\"24\" :sm=\"12\" :lg=\"6\">");
			}
			if (rowCol > 0 && strBuf.length() > 0) {
				String result = strBuf.toString();
				strBuf = new StrBuf(true);
				strBuf.append(tab, "<el-row>");
				strBuf.append(result);
				strBuf.append(tab, "</el-row>");
			}
		}
		return strBuf.toString();
	}

	// 一对多表单添加或者编辑
	private String getTabPane(int tab) {
		StrBuf buffer = new StrBuf(true);
		for (Link link : links) {
			if (link == null || link.getLinkTable() == null || !link.getLinkSave()) {
				continue;
			}
			String lnkTblName = getLinkPropName(link);
			buffer.append(tab, "<el-tab-pane label=\"{1}\">", link.getLinkTable().getCmmt());
			buffer.append(tab + 1, "<el-button-group style=\"margin-bottom:10px\">");
			buffer.append(tab + 2, "<el-button size=\"small\" type=\"primary\" icon=\"el-icon-edit\" @click=\"func.onAdd(formData.{1}List)\">新增</el-button>", lnkTblName);
			buffer.append(tab + 1, "</el-button-group>");
			buffer.append(tab + 1, "<el-table v-loading=\"listData.loading\" :data=\"formData.{1}List\" element-loading-text=\"载入中...\" size=\"mini\" border fit highlight-current-row>", lnkTblName);
			if (link.getLinkTable() != null && link.getLinkTable().getColumnList() != null) {
				// || Constant.ID_NAME.equals(column.getName())
				link.getLinkTable().getColumnList().stream().filter(cln -> isTrue(cln.getFormShow())
						&& !link.getLinkColumnId().equals(cln.getId())).forEach(cln ->
						buffer.append(getFormItem(cln, "scope.row", tab + 2, lnkTblName)));
			}
			buffer.append(tab + 2, "<el-table-column align=\"center\" fixed=\"right\" label=\"操作\" width=\"65px\">");
			buffer.append(tab + 3, "<template slot-scope=\"scope\">");
			buffer.append(tab + 4, "<el-button type=\"danger\" size=\"mini\" @click=\"func.onDel(formData.{1}List, scope.$index)\"><i class=\"el-icon-close\" /></el-button>", lnkTblName);
			buffer.append(tab + 3, "</template>");
			buffer.append(tab + 2, "</el-table-column>");
			buffer.append(tab + 1, "</el-table>");
			buffer.append(tab, "</el-tab-pane>");
		}
		String back = buffer.toString();
		return back.length() > 0 ? back.substring(0, back.length() - 1) : back;
	}

	// 获取单个form表单
	private String getFormItem(Column cln, String data, int tab, String lnkTblName) {
		int rowCol = table.getRowCol() == null || table.getRowCol() < 0 ? 0 : table.getRowCol();
		tab = tab + (StrUtil.isBlank(lnkTblName) && rowCol > 0 ? 2 : 0);
		StrBuf strBuf = new StrBuf(true);
		String clnName = AutoUtil.firstLowerBean(cln.getName());
		String result = getFormItemElem(cln, data, !StrUtil.isBlank(lnkTblName), tab);
		if ("scope.row".equals(data)) {
			String rules = getRules(cln).replace("},]", "}]");
			String prop = StrUtil.format("`{}List[`+scope.$index+`].{}`", lnkTblName, clnName);
			strBuf.append(tab, "<el-table-column align=\"center\" label=\"{1}\">", getCmmt(cln, ""));
			strBuf.append(tab + 1, "<template slot-scope=\"scope\">");
			strBuf.append(tab + 2, "<el-form-item :rules=\"{1}\" :prop=\"{2}\" label-width=\"0\" style=\"margin-top:15px\">", rules, prop);
			strBuf.append(tab + 3, result);
			strBuf.append(tab + 2, "</el-form-item>");
			strBuf.append(tab + 1, "</template>");
			strBuf.append(tab, "</el-table-column>");
		} else {
			strBuf.append(tab, "<el-form-item label=\"{1}\" prop=\"{2}\"{3}>", getCmmt(cln, "").replace("ID", ""), clnName, isRequired(cln) ? " required" : "");
			strBuf.append(tab + 1, result);
			strBuf.append(tab, "</el-form-item>");
		}
		return strBuf.toString();
	}

	// 获取form表单元素
	private String getFormItemElem(Column cln, String data, boolean isLink, int tab) {
		ClnType clnType = ClnType.find(cln.getType());
		FormType formType = FormType.find(cln.getFormType());

		String comment = getCmmt(cln, "");
		String clnName = AutoUtil.firstLowerBean(cln.getName());
		String model = "v-model=\""+(data + "." + clnName)+"\"";
		String holder = "placeholder=\""+getHolder(formType, comment, isLink)+"\"";

		if (formType == null) {
			throw new MsgException("请选择" + cln.getName() + "的表单类型!");
		}
		if (!isLink && (formType == FormType.SELECT || formType == FormType.MY_CONF)) {
			return getMyComp(formType, cln.getLinkTable(), table.getName(), data + "." + clnName, comment);
		}
		else if (formType == FormType.DATE || formType == FormType.TIME) {
			String type = formType == FormType.DATE ? "" : " type=\"datetime\"";
			String format = formType == FormType.DATE ? "yyyy-MM-dd" : "yyyy-MM-dd HH:mm:ss";
			return StrUtil.format("<el-date-picker {} {}{} value-format=\"{}\" clearable />", model, holder, type, format);
		}
		else if (formType == FormType.NUMBER) {
			int min = cln.getValidMin() != null ? cln.getValidMin() : 0;
			String max = cln.getValidMax() != null ? " :max=\"" + cln.getValidMax() + "\"" : "";
			String dotRight = cln.getDotRight() != null ? " :precision=\""+cln.getDotRight()+"\"" : "";
			return StrUtil.format("<el-input-number {} :min=\"{}\"{}{} :controls=\"false\" clearable />", model, min, max, dotRight);
		}
		else if (formType == FormType.RADIO || formType == FormType.CHECKBOX) {
			if (clnType == ClnType.BOOLEAN) {
				return StrUtil.format("<el-switch {} active-color=\"#13ce66\" inactive-color=\"#ff4949\" />", model);
			}
			String mul = formType == FormType.RADIO ? "" : " multiple";
			String opts = StrBuf.tabStr(2, true) + "<el-option value=\"\" label=\"\" />";
			if (!StrUtil.isEmpty(cln.getLimits()) && !cln.getName().equals(Constant.CLN_STATUS)) {
				opts = getLimitsHtml(cln.getLimits(), tab + 2, null);
			}
			return StrUtil.format("<el-select {} {} clearable{}>\n{}{}</el-select>", model, holder, mul, opts, StrBuf.tabStr(tab + 2, true));
		}
		else if (formType == FormType.MUL_INPUT) {
			long max = cln.getValidMax() == null ? cln.getLength() : cln.getValidMax();
			String limit = max > 0 ? StrUtil.format("maxlength=\"{}\" show-word-limit ", max) : "";
			return StrUtil.format("<el-input {} :autosize=\"{ minRows: 3 }\" {} type=\"textarea\" {}clearable />", model, holder, limit);
		}
		else if (formType == FormType.RICH_TEXT) {
			return StrUtil.format("<div class=\"editor-container\"><my-editor ref=\"editor\" {} /></div>", model);
		}
		else if (formType == FormType.IMAGE || formType == FormType.FILE) {
			return StrUtil.format("<upload-one {} :type=\"{}\" :limit=\"1\" dir=\"test\" />", model, formType == FormType.IMAGE ? 1 : 2);
		}
		else if (formType == FormType.SECRET) {
			return StrUtil.format("<el-input {} {} show-password clearable />", model, holder);
		}
		else if (formType == FormType.INPUT) {
			long length = cln.getValidMax() == null ? cln.getLength() : cln.getValidMax();
			String limit = length > 0 ? StrUtil.format("maxlength=\"{}\" show-word-limit ", length) : "";
			return StrUtil.format("<el-input {} {} {}clearable />", model, holder, limit);
		}
		else {
			return StrUtil.format("<el-input {} {} clearable />", model, holder);
		}
	}

	// 获取表单验证规则
	private StringBuffer getFormRules() {
		StringBuffer buffer = new StringBuffer();
		for (Column column : columns) {
			//TODO 图片上传需要提示
			if (!isTrue(column.getFormShow()) || FormType.find(column.getFormType()) == FormType.IMAGE) {
				continue;
			}
			String rules = getRules(column);
			if (rules.length() > 2) {
				rules = rules.replace("[{", "[\n          {");
				rules = rules.replace("},{", "},\n          {");
				rules = rules.replace("},]", "}\n        ]");
				if (buffer.length() > 0) {
					buffer.append(",\n");
				}
				buffer.append("        ").append(AutoUtil.firstLowerBean(column.getName())).append(": ").append(rules);
			}
		}
		return AutoUtil.moveLastDot(buffer);
	}

	// 获取单个字段验证规则
	private String getRules(Column cln) {
		String result = "[";
		if (!(cln.isInteger() || cln.isDecimal() || cln.isDouble() || cln.isFloat() || cln.isLong())) {
			if (cln.getValidMin() != null && cln.getValidMax() != null) {
				result += StrUtil.format("{ min: {}, max: {}, message: '长度在 {} 到 {} 个字符', trigger: ['blur', 'change'] },", cln.getValidMin(), cln.getValidMax(), cln.getValidMin(), cln.getValidMax());
			} else if (cln.getValidMin() != null) {
				result += StrUtil.format("{ min: {}, message: '长度最少 {} 个字符', trigger: ['blur', 'change'] },", cln.getValidMin(), cln.getValidMin());
			}
		}
		if (!StrUtil.isEmpty(cln.getValidFun())) {
			result += StrUtil.format("{ {}validator: {}, trigger: ['blur', 'change'] },", isRequired(cln) ? "required: true, " : "", cln.getValidFun());
		} else if (isRequired(cln)) {
			result += StrUtil.format("{ {}required: true, message: '请{}{}', trigger: ['blur', 'change'] },", cln.isDate() ? "type: 'date', " : "", cln.getFormType() == 2 ? "选择" : "输入", cln.getCmmt().replace("ID", ""));
		}
		return result + "]";
	}

	private String getHolder(FormType formType, String comment, boolean isLink) {
		if (formType == FormType.SELECT && !isLink) {
			return comment.replace("ID", "名");
		}
		if (formType == FormType.RADIO || formType == FormType.CHECKBOX) {
			return "请选择" + comment;
		}
		return "请输入" + comment;
	}
	
	private boolean isRequired(Column cln) {
		return (cln.getRequired() == null && cln.getNotNull()) || (cln.getRequired() != null && cln.getRequired());
	}

	// 导入导出数据结构
	private StringBuffer getTableMap(String blank) {
		StringBuffer filter = new StringBuffer();
		columns.stream().filter(cln -> isTrue(cln.getListShow())).forEach(cln -> {
			filter.append(blank).append("'").append(getCmmt(cln,"名"));
			filter.append("': '").append(getColumnExportProp(cln)).append("',\n");
		});
		if (filter.toString().endsWith(",\n")) {
			filter.setLength(filter.length() - 2);
		}
		return filter;
	}

	private String getColumnExportProp(Column cln) {
		String columnName = AutoUtil.firstLowerBean(cln.getName());
		// || cln.isBoolean()
		if (!StrUtil.isEmpty(cln.getLimits())) {
			return columnName+"Text";
		} else if (cln.getLinkTable() != null) {
			return AutoUtil.firstLowerBean(cln.getName().replace("_id", ""))+".name";
		}
		return columnName;
	}

	// 限制html
	private String getLimitsHtml(String limitStr, int tab, String slotClnName) {
		Limits limits = new Limits(limitStr);
		StrBuf result = new StrBuf(true);
		for (Limits.Dict dict : limits.getDictList()) {
			String prev = dict.getIntKey() == null ? dict.getStrKey() : dict.getIntKey() + "";
			String next = dict.getValue();
			if (slotClnName == null) {
				if (dict.getIntKey() == null) {
					result.append(tab,"<el-option value=\"{1}\" label=\"{2}\" />", prev, next);
				} else {
					result.append(tab,"<el-option :value=\"{1}\" label=\"{2}\" />", prev, next);
				}
			} else {
				if (dict.getIntKey() == null) {
					prev = "'" + prev + "'";
				}
				result.append(tab,"<el-tag v-if=\"{1} == {2}\" size=\"mini\">{3}</el-tag>", slotClnName, prev, next);
			}
		}
		return result.toString();
	}
	
	private boolean isShowInDetail(Column cln) {
		ClnType clnType = ClnType.find(cln.getType());
		return clnType == ClnType.TEXT || clnType == ClnType.BLOB || cln.getLength() > 1024; //cln.getLength() >= 1024
	}

	public String fillByKey(String fileTxt, String key, StringBuffer value) {
		int start = fileTxt.indexOf(key);
		String temp = fileTxt.substring(0, start);
		temp = temp.substring(temp.lastIndexOf("\n") + 1);
		String endKey = key.replace("开始", "结束");
		int end = fileTxt.indexOf(endKey);
		if (key.startsWith("//")) {
			int index = fileTxt.lastIndexOf("\n", start);
			if (key.equals("// 自动生成引入代码开始")) {
				index = start;
				fileTxt = fileTxt.replace(fileTxt.substring(index, end + endKey.length() + 2), value);
			} else {
				index = index + 2;
				fileTxt = fileTxt.replace(fileTxt.substring(index, end + endKey.length() + 2), value);
			}
		} else {
			fileTxt = fileTxt.replace(fileTxt.substring(start, end), key + "\n" + value + temp);
		}
		return fileTxt;
	}

	public String fillByKey(String fileTxt, String key, String value) {
		return !StrUtil.isBlank(value) ? fileTxt.replace(key, key + "\n" + value) : fileTxt;
	}

	public String fillBeforeKey(String fileTxt, String key, String value) {
		return !StrUtil.isBlank(value) ? fileTxt.replace(key, value + "\n" + key) : fileTxt;
	}

	//填充编辑表单
	public StringBuffer getEditFormData() {
		StringBuffer buffer = new StringBuffer(); String before = "        ";
		for (Column column : columns) {
			if (column.getLinkTable() != null && column.getLinkSave() != null && column.getLinkSave()) {
				buffer.append(before).append(AutoUtil.firstLowerBean(column.getLinkTable().getName())).append(": {},\n");
			}
		}
		for (Link link : links) {
			if (link != null && link.getLinkTable() != null && link.getLinkSave() != null && link.getLinkSave()) {
				buffer.append(before).append(getLinkPropName(link)).append("List: [],\n");
			}
		}
		return AutoUtil.moveLastDot(buffer); //.append("\n      ");
	}

	public String getCmmt(Column cln, String last) {
		String comment = cln.getCmmt().replaceAll("\\[.*\\]", "");
		if (last != null && cln.getLinkTable() != null && comment.endsWith("ID")) {
			return comment.substring(0, comment.length() - 2) + last;
		}
		return comment;
	}
}
